package com.sumer.psychology.blog.application.command;

import com.sumer.psychology.blog.domain.model.*;
import com.sumer.psychology.common.Assert;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;

/**
 * Blog应用服务
 * <p/>
 * User: zhenguang.zhu
 * Date: 2014/8/11
 * Time: 10:22
 */
@Transactional(rollbackFor = Exception.class)
public class BlogApplicationService {
    private BlogRepository blogRepository;
    private CategoryRepository categoryRepository;

    public BlogApplicationService(BlogRepository blogRepository, CategoryRepository categoryRepository) {
        this.blogRepository = blogRepository;
        this.categoryRepository = categoryRepository;
    }

    /**
     * 新增一个blog
     *
     * @param aCreateBlogCommand command
     */
    public BlogId newBlog(CreateBlogCommand aCreateBlogCommand) {
        Blog aBlog = BlogFactory.instance().createBlog(
                aCreateBlogCommand,
                blogRepository(),
                categoryRepository());

        blogRepository().add(aBlog);
        return aBlog.blogId();
    }

    /**
     * 修改一个blog
     *
     * @param aChangeBlogCommand command
     */
    public void changeBlog(ChangeBlogCommand aChangeBlogCommand) {
        Blog aBlog = activeBlog(aChangeBlogCommand.identity());
        Assert.notNull(aBlog, "没有找到对应的Blog");

        aBlog.change(// 必须修改的
                aChangeBlogCommand.title(),
                aChangeBlogCommand.content());

        if (StringUtils.isNoneBlank(aChangeBlogCommand.categoryId())) {// 可能会修改category
            categorize(new CategorizeBlogCommand(
                    aChangeBlogCommand.identity(),
                    aChangeBlogCommand.categoryId()));
        }
    }

    /**
     * 拉进回收站
     *
     * @param toRecycleBinCommand command
     */
    public void recycleBin(PutBlogToRecycleBinCommand toRecycleBinCommand) {
        Blog aBlog = activeBlog(toRecycleBinCommand.identity());
        Assert.notNull(aBlog, "没有找到对应的Blog");

        aBlog.recycleBin();
    }

    /**
     * 从回收站恢复
     *
     * @param aRestoreBlogCommand command
     */
    public void restore(RestoreBlogCommand aRestoreBlogCommand) {
        Blog aBlog = blogRepository().blogOfId(
                new BlogId(aRestoreBlogCommand.identity()),
                BlogAvailability.DEACTIVE);
        Assert.notNull(aBlog, "没有找到对应的Blog");

        aBlog.restore();
    }

    /**
     * 彻底删除Blog
     *
     * @param aDeleteBlogCommand command
     */
    public void deleteCompletely(DeleteBlogCommand aDeleteBlogCommand) {
        Blog aBlog = blogRepository().blogOfId(new BlogId(aDeleteBlogCommand.identity()));

        if (aBlog != null) {
            aBlog.deleteCompletely();
        }
    }

    /**
     * 归类
     *
     * @param categorizeBlogCommand command
     */
    public void categorize(CategorizeBlogCommand categorizeBlogCommand) {
        Blog aBlog = activeBlog(categorizeBlogCommand.blogId());

        Category aCategory = categoryRepository().activeCategoryOfId(
                new CategoryId(categorizeBlogCommand.categoryId()));

        Assert.notNull(aBlog, "没有找到对应的Blog");
        Assert.notNull(aCategory, "没有找到对应的目录");

        aBlog.categorizeInto(aCategory);
    }

    /**
     * 删除分类
     *
     * @param deleteCategoryCommand command
     */
    public void removeCategoryOfBlogs(DeleteCategoryCommand deleteCategoryCommand) {
        Category aCategory = categoryRepository().categoryOfId(
                new CategoryId(deleteCategoryCommand.deletedId()));
        Assert.notNull(aCategory, "目录为空");

        Set<Blog> blogs = aCategory.blogs();

        for (Blog blog : blogs) {
            blog.removeCategory();
        }
    }

    /**
     * 设置精华
     *
     * @param labelBestBlogCommand command
     */
    public void recommend(RecommendBlogCommand labelBestBlogCommand) {
        Blog aBlog = activeBlog(labelBestBlogCommand.blogId());
        Assert.notNull(aBlog, "没有找到对应的Blog");
        aBlog.recommend();
    }

    /**
     * 删除精华
     *
     * @param removeBestBlogCommand command
     */
    public void cancleRecommendation(CancelBlogRecommendationCommand removeBestBlogCommand) {
        Blog aBlog = activeBlog(removeBestBlogCommand.blogId());
        Assert.notNull(aBlog, "没有找到对应的Blog");
        aBlog.cancelRecommendation();
    }

    /*
     * 激活的blog
     */
    private Blog activeBlog(String aBlogId) {
        return blogRepository().blogOfId(
                new BlogId(aBlogId),
                BlogAvailability.ACTIVE);
    }

    private BlogRepository blogRepository() {
        return blogRepository;
    }

    public CategoryRepository categoryRepository() {
        return categoryRepository;
    }
}
